﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Net.Mail;
using System.IO;
using System.Reflection;
using System.Drawing;
using Ahi.Config;

namespace Utilities.Logging
{
    internal class ALogger
    {
        #region Members
        private Stopwatch stopwatch;
        private Stack<string> traceKeys;
        #endregion

        #region Singleton Instance
        private ALogger()
        {
            Debug.AutoFlush = true;
            stopwatch = new Stopwatch();
            traceKeys = new Stack<string>();
            StartLog();
        }

        private static ALogger _instance = null;
        public static ALogger Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new ALogger();
                return _instance;
            }
        }
        #endregion

        #region Util Methods
        private string PadString(string str, int length, char paddingChar = '*')
        {
            int padLenght = length - (str.Length / 2);
            return str.PadLeft(str.Length + padLenght, paddingChar).PadRight(str.Length + padLenght * 2, paddingChar);
        }

        private string GetRandomFileName
        {
            get
            {
                return Path.Combine(AppConfig.Current.LogDirectory, Path.GetRandomFileName().Replace(".", ""));
            }
        }

        private string GetFileExtension(string filePath)
        {
            return filePath.Substring(filePath.LastIndexOf("."), filePath.Length - filePath.LastIndexOf("."));
        }
        #endregion

        public void StartLog()
        {
            if (!Directory.Exists(AppConfig.Current.LogDirectory))
                Directory.CreateDirectory(AppConfig.Current.LogDirectory);

            Debug.Listeners.Add(new TextWriterTraceListener(AppConfig.Current.LogTxtDosyasi, AppConfig.Current.TextLogAdi));
            string logMessage = string.Format("{0} tarihinde, {1} kullanıcısı, {2} isimli makinede {3} {4} uygulamasını başlattı.",
                DateTime.Now,
                Environment.UserName,
                Environment.MachineName,
                AppConfig.Current.AppName,
                AppConfig.Current.AppVersion);

            Debug.WriteLine(PadString(logMessage, 80));
            Debug.WriteLine(PadString(string.Format("OS : {0}, .Net Versiyon: {1}", Environment.OSVersion, Environment.Version), 80, '-'));
        }

        public void FinishLog()
        {
            Debug.WriteLine(PadString(string.Format("{0} tarihinde uygulama kapatıldı", DateTime.Now), 100));
            Debug.Listeners.Remove(AppConfig.Current.TextLogAdi);
        }

        public void LogException(Exception ex, Severity severity)
        {
            string logMessage = string.Format(@"{0} -> {1} - {2}
Stack Trace:{3}
{4}",
                    DateTime.Now,
                    severity,
                    ex.Message,
                    Environment.StackTrace,
                    PadString("", 80, '-'));

            Debug.WriteLine(logMessage);
        }

        public void LogMessage(string message, Severity severity = Severity.Information, params object[] arguaments)
        {
            string rawMessage = null;
            if (arguaments != null && arguaments.Length > 0)
                rawMessage = string.Format(message, arguaments);
            else
                rawMessage = message;

            string logMessage = string.Format(@"{0} -> {1} - {2}",
                   DateTime.Now.ToString("T"),
                   severity,
                   rawMessage);

            Debug.WriteLine(logMessage);
        }

        public void StartTrace(string traceKey)
        {
            stopwatch.Reset();
            stopwatch.Start();
            this.traceKeys.Push(traceKey);
            LogMessage("{0} işlemi başlatıldı.", Severity.Trace, traceKey);
        }

        public long StopTrace()
        {
            stopwatch.Stop();
            LogMessage("{0} işlemi {1} milisaniyede tamamlandı.", Severity.Trace, this.traceKeys.Pop(), stopwatch.ElapsedMilliseconds);
            return stopwatch.ElapsedMilliseconds;
        }

        public string LogBitmap(Bitmap bmp, string traceName = "Bitmap Save")
        {
            string fileName = null;
            try
            {
                if (bmp == null)
                    ALogger.Instance.LogMessage("Bitmap Loglama başarısız. Bitmap NULL olamaz.", Severity.Warning);
                fileName = GetRandomFileName + ".tiff";
                StartTrace(traceName);
                bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Tiff);
                StopTrace();
            }
            catch (Exception ex)
            {
                ALogger.Instance.LogException(ex, Severity.Error);
            }
            return fileName;
        }

        public void LogBitmap(string imageFilePath)
        {
            if (string.IsNullOrEmpty(imageFilePath))
            {
                ALogger.Instance.LogMessage("Image dosya yolu null olamaz! Adresi verilen bitmap loglanamadı!", Severity.Error);
                return;
            }

            try
            {
                string fileName = GetRandomFileName + GetFileExtension(imageFilePath);
                File.Copy(imageFilePath, fileName);
            }
            catch (Exception ex)
            {
                this.LogException(ex, Severity.Error);
                throw;
            }
        }

        public void ShowTxtLogFile()
        {
            using (var proc = Process.Start("notepad.exe", AppConfig.Current.LogTxtDosyasi, null, null, null))
            {
            }
        }

        public void SendTxtLogFileWithEmail()
        {
            using (var proc = Process.Start("mailto:alfabcsoft@gmail.com?" +
                "subject=Ahi Dernek Programı Hata Raporu&" +
                "body=Ahi Dernek Yönetim programını kullanırken oluşan hata raporu dosyasını ektedir&" +
                "Attachment=" + AppConfig.Current.LogTxtDosyasi, null, null, null))
            {
            }
        }

        public enum Severity
        {
            None = 0,
            Information = 1,
            Warning = 2,
            Error = 3,
            Critical = 4,
            Trace = 5
        }
    }
}
